package org.soulraven.games.memory.engine;

import java.util.List;

import org.apache.log4j.Logger;
import org.soulraven.games.memory.model.Game;
import org.soulraven.games.memory.model.Player;
import org.soulraven.games.memory.ui.game.GameFrame;
import org.soulraven.games.memory.ui.game.controller.SelectionController;

public abstract class BaseMemoryEngine implements MemoryEngine {

	private static final Logger LOGGER = Logger.getLogger(BaseMemoryEngine.class);

	protected List<Player> players = null;
	protected int currentPlayerIndex;
	protected GameFrame gameFrame = null;
	private SelectionController selectionController = null;
	private int matchesInARow;

	public BaseMemoryEngine() {
		init();
	}

	public void init() {
		matchesInARow = 0;
		currentPlayerIndex = 0;
		LOGGER.debug("Creating SelectionController");
		selectionController = new SelectionController(this);
		LOGGER.debug("SelectionController created");
	}

	public void start(final Game game, final List<Player> players) {
		this.players = players;
		LOGGER.debug("Creating GameFrame");
		gameFrame = new GameFrame(this, game);
		LOGGER.debug("GameFrame created");
		gameFrame.setVisible(Boolean.TRUE);
	}

	/**
	 * @return the currentPlayer
	 */
	public Player getCurrentPlayer() {
		return players.get(currentPlayerIndex);
	}

	/**
	 * @return the selectionController
	 */
	public SelectionController getSelectionController() {
		return selectionController;
	}

	public void pairShown(final boolean match) {
		gameFrame.pairShown(match);
	}

	@Override
	public void matchesNotFound() {
		matchesInARow = 0;
	}

	public void matchesFound() {
		Player currentPlayer = getCurrentPlayer();
		computeNewScore(currentPlayer);
		gameFrame.updateStatusBar(currentPlayer);
		checkEndGame();
	}

	@Override
	public void computeNewScore(final Player player) {
		player.setScore(player.getScore() + (1 * ++matchesInARow));
	}

	public void disableAllCards() {
		gameFrame.disableAllCards();
	}

	public void enableAllSelectableCards() {
		gameFrame.enableAllSelectableCards();
	}

	public void checkEndGame() {
		if (gameFrame.isEndGame()) {
			processEndGame();
		}
	}
}
